Imports System.IO
Imports System.Text
Imports System.Security.Cryptography

Public Class clsSerial
    Private intNumTries As Integer = 0
    Private Const MAX_TRIES As Integer = 5

    Private Function trackNumAttempts() As Boolean
        ' Purpose:
        '   Ensures that we have not exceeded the number of attempts we wish to provide the user to 'crack' the serial
        ' Postconditions:
        '   Returns true if user has exceeded number of attempts, else false

        ' Track number of attempts regardless of wheither they're processed or not
        intNumTries = intNumTries + 1

        If intNumTries >= MAX_TRIES Then
            ' No more attempts permitted
            Return True
        Else
            Return False
        End If
    End Function

    Private Function fetchSNData(ByVal strSerial As String) As String
        Dim strLocalFile As String
        Dim strRemoteFile As String
        Dim strFileContents As String

        strRemoteFile = "http://serials.terranika.com/verify/" & strSerial & ".sn"
        strLocalFile = My.Computer.FileSystem.SpecialDirectories.Temp & "\" & Now().ToString & ".sn"

        ' Download the file
        Try
            My.Computer.Network.DownloadFile(strRemoteFile, strLocalFile)
        Catch
            ' Assume firewalled because of piracy
            Return ""
            Exit Function
        End Try

        ' Store what was in the file into RAM
        strFileContents = My.Computer.FileSystem.ReadAllText(strLocalFile)

        ' Delete the file
        My.Computer.FileSystem.DeleteFile(strLocalFile)

        ' Simply return the contents of the file
        Return strFileContents
    End Function

    Private Function verifyWithOnlineDB(ByVal strSerial As String) As Boolean
        ' Purpose:
        '   Given a serial, determine if valid
        ' Postconditions:
        '   Returns true if offline or valid serial
        '   Returns false if unexpected response received (i.e. invalid hash)
        Dim strServerResponse As String
        Dim strExpectedResponse As String

        ' Verify internet connection
        If My.Computer.Network.IsAvailable = False Then
            ' Not connected to internet
            Return True
            Exit Function
        End If

        ' Get data from remote server
        strServerResponse = fetchSNData(strSerial)

        ' Expect to receive MD5 hash of serial sent
        strExpectedResponse = GenerateMD5Hash(strSerial)

        ' Did the serial get echoed back as a hash?
        '   If so, then we're good
        If strServerResponse = strExpectedResponse Then
            Return True
        Else
            Return False
        End If
    End Function

    Public Function VerifySerial(ByVal strSerial As String) As Boolean
        ' Purpose:
        '   To verify if serial number is valid (VIA Internet)
        ' Postconditions:
        '   Returns true if valid serial number
        '   Returns false if too many attempts have been made or invalid serial number

        ' Ensure not too many attempts of cracking have been made
        If trackNumAttempts() Then
            Return False
            Exit Function
        End If

    End Function

    Private Function GenerateMD5Hash(ByVal SourceText As String) As String
        ' Code taken from: http://www.a1vbcode.com/vbtip-149.asp

        'Create an encoding object to ensure the encoding standard for the source text
        Dim Ue As New UnicodeEncoding()

        'Retrieve a byte array based on the source text
        Dim ByteSourceText() As Byte = Ue.GetBytes(SourceText)

        'Instantiate an MD5 Provider object
        Dim Md5 As New MD5CryptoServiceProvider()

        'Compute the hash value from the source
        Dim ByteHash() As Byte = Md5.ComputeHash(ByteSourceText)

        'And convert it to String format for return
        Return Convert.ToBase64String(ByteHash)
    End Function
End Class
